package com.eshop.utils;

import org.springframework.util.DigestUtils;
import javax.crypto.SecretKey;
import java.security.spec.AlgorithmParameterSpec;
import java.security.Key;
import java.security.spec.KeySpec;
import javax.crypto.SecretKeyFactory;
import java.nio.charset.StandardCharsets;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.Cipher;

public class EncryptUtils
{
    private static String strParam;
    private static Cipher cipher;
    private static IvParameterSpec iv;
    
    private static DESKeySpec getDesKeySpec(final String source) throws Exception {
        if (source == null || source.length() == 0) {
            return null;
        }
        EncryptUtils.cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
        final String strKey = "Passw0rd";
        return new DESKeySpec(strKey.getBytes(StandardCharsets.UTF_8));
    }
    
    public static String desEncrypt(final String source) throws Exception {
        final DESKeySpec desKeySpec = getDesKeySpec(source);
        final SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        final SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
        EncryptUtils.cipher.init(1, secretKey, EncryptUtils.iv);
        return byte2hex(EncryptUtils.cipher.doFinal(source.getBytes(StandardCharsets.UTF_8))).toUpperCase();
    }
    
    public static String desDecrypt(final String source) throws Exception {
        final byte[] src = hex2byte(source.getBytes());
        final DESKeySpec desKeySpec = getDesKeySpec(source);
        final SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        final SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
        EncryptUtils.cipher.init(2, secretKey, EncryptUtils.iv);
        final byte[] retByte = EncryptUtils.cipher.doFinal(src);
        return new String(retByte);
    }
    
    private static String byte2hex(final byte[] inStr) {
        final StringBuilder out = new StringBuilder(inStr.length * 2);
        for (final byte b : inStr) {
            final String stmp = Integer.toHexString(b & 0xFF);
            if (stmp.length() == 1) {
                out.append("0").append(stmp);
            }
            else {
                out.append(stmp);
            }
        }
        return out.toString();
    }
    
    private static byte[] hex2byte(final byte[] b) {
        final int size = 2;
        if (b.length % size != 0) {
            throw new IllegalArgumentException("长度不是偶数");
        }
        final byte[] b2 = new byte[b.length / 2];
        for (int n = 0; n < b.length; n += size) {
            final String item = new String(b, n, 2);
            b2[n / 2] = (byte)Integer.parseInt(item, 16);
        }
        return b2;
    }
    
    public static String encryptPassword(final String password) {
        return DigestUtils.md5DigestAsHex(password.getBytes());
    }
    
    static {
        EncryptUtils.strParam = "Passw0rd";
        EncryptUtils.iv = new IvParameterSpec(EncryptUtils.strParam.getBytes(StandardCharsets.UTF_8));
    }
}
